home *** CD-ROM | disk | FTP | other *** search
/ Workbench Add-On / Workbench Add-On - Volume 1.iso / Music / MIDI / mod2midi / mod2midi.c < prev    next >
C/C++ Source or Header  |  1995-08-23  |  43KB  |  1,989 lines

  1. /*    .MOD to MID file converter ©1993 Andrew Scott
  2.  
  3.         Amiga conversion © 1994 by Paul Huxham
  4. */
  5.  
  6. #include <ctype.h>
  7. #include <math.h>
  8. #include <stdio.h>
  9. #include <stdlib.h>
  10. #include <string.h>
  11.  
  12. #include <exec/types.h>
  13.  
  14. #include <clib/dos_protos.h>
  15.  
  16. #include <pragmas/dos_pragmas.h>
  17.  
  18. #include "mod2midi.h"
  19. #include "text.h"
  20.  
  21. /* CLI parameters */
  22. #define OPT_TEMPLATE "MOD,MIDI,ABOUT/S,MAPSAMPLES/S,SAVEINFO/S,TRANSPOSE/S,DRUM/N,TEMPO/N,VOLUMESHIFT/S"
  23. #define OPT_MODFILE 0
  24. #define OPT_MIDIFILE 1
  25. #define OPT_ABOUT 2
  26. #define OPT_MAPSAMPLES 3
  27. #define OPT_SAVEINFO 4
  28. #define OPT_TRANSPOSE 5
  29. #define OPT_DRUMCHANNEL 6
  30. #define OPT_TEMPOTYPE 7
  31. #define OPT_VOLUMESHIFT 8
  32. #define OPT_NUMBEROF 9
  33.  
  34. /* Function Prototypes */
  35. int Instrument( void );
  36. void OutByte( bfile f, char b );
  37. void FlushOut( bfile f );
  38. void CloseOut( bfile f );
  39. int OpenOut( bfile f, string fn );
  40. unsigned long Beatle( bfile f );
  41. unsigned char InByte( bfile f );
  42. void CloseIn( bfile f );
  43. int OpenIn( bfile f, string fn );
  44. void Inskipp( bfile f, unsigned long n );
  45. struct bpos FPos( bfile f );
  46. void FGoto( bfile f, struct bpos x );
  47. int WriteVLQ( bfile f, unsigned long i );
  48. int MKTest( bfile f );
  49. string SimplifyName( string s );
  50. string GetLine( FILE *f );
  51. int ReadModSpecs( bfile f, string n, samps s );
  52. void ScanSamples( samps s );
  53. int SetDefaults( samps s, string fn );
  54. void SaveDefaults( samps s, string fn );
  55. void NullArryFree( string *sp );
  56. int Instrument();
  57. string MIDIVal( samp *sam );
  58. string TransVal( samp *sam );
  59. string VolumeVal( samp *sam );
  60. string NullVal( samp *sam );
  61. int Sample( samps s, string (*MIDIVal)(samp *x), int w );
  62. int ChooseChannels( samps s );
  63. void MapSamples( samps s );
  64. void SaveSamp( samp sam );
  65. void SaveSamples( samps s );
  66. void Transpositions( samps s );
  67. void VolumeShifts( samps s );
  68. unsigned char NoteValue( unsigned int n );
  69. unsigned long NoteLength( unsigned char n, unsigned int l, unsigned int b );
  70. void WriteHeader( bfile mf, unsigned char n );
  71. unsigned int Trk0Info( bfile mf, string s );
  72. void AddToLog( unsigned long a, unsigned long b );
  73. void WriteLog( FILE *f );
  74. unsigned char RestrictVol( int v );
  75. void ConvertMOD( bfile f1, bfile f2, string tn, samps smp );
  76. extern int ScrollChoice( string title, string *sp, int w );
  77. extern string DialogBox( string *sp, string def );
  78.  
  79. char *version = "$VER: Mod2Midi 1.0 (12.6.94)";
  80. long __stack = 20000; // Code allocates everything off the stack ;-)
  81.  
  82. bfile MidFile, ModFile;
  83. char SongName[21];
  84. samps Samples;
  85. unsigned long PosLog[64];
  86. int DrumChann = 9, TempoType = 1, PosI = 0;
  87. string MidFN, ModFN;
  88.  
  89. char *TempoTypes[] = { "NORMAL", "EXTENDED" };
  90.  
  91. extern struct Library *DOSBase;
  92.  
  93. int main( int argc, char *argv[] )
  94. {
  95.     int r;
  96.     UBYTE Mode = MODE_CONVERT;
  97.  
  98.     MidFile->f = ModFile->f = NULL;
  99.     MidFN = ModFN = NULL;
  100.  
  101.     /* Only work if launched from shell */
  102.     if ( argc != 0 )
  103.     {
  104.         struct RDArgs *RDArgs;
  105.         LONG opts[OPT_NUMBEROF];
  106.  
  107.         opts[OPT_MODFILE] = 0;
  108.         opts[OPT_MIDIFILE] = 0;
  109.         opts[OPT_ABOUT] = 0;
  110.         opts[OPT_MAPSAMPLES] = 0;
  111.         opts[OPT_SAVEINFO] = 0;
  112.         opts[OPT_TRANSPOSE] = 0;
  113.         opts[OPT_DRUMCHANNEL] = 0;
  114.         opts[OPT_TEMPOTYPE] = 0;
  115.         opts[OPT_VOLUMESHIFT] = 0;
  116.  
  117.         RDArgs = ReadArgs( OPT_TEMPLATE, opts, NULL );
  118.         if ( RDArgs != NULL )
  119.         {
  120.             /* Grab all set cli parameters */
  121.             if ( opts[OPT_MODFILE] != 0 )
  122.             {
  123.                 ModFN = malloc( strlen( (char *)opts[OPT_MODFILE] ) + 1 );
  124.                 if ( ModFN != NULL ) strcpy( ModFN, (char *)opts[OPT_MODFILE] );
  125.             }
  126.  
  127.             if ( opts[OPT_MIDIFILE] != 0 )
  128.             {
  129.                 MidFN = malloc( strlen( (char *)opts[OPT_MIDIFILE] ) + 1 );
  130.                 if ( MidFN != NULL ) strcpy( MidFN, (char *)opts[OPT_MIDIFILE] );
  131.             }
  132.  
  133.             if ( opts[OPT_ABOUT] != 0 )    Mode |= MODE_ABOUT;
  134.  
  135.             if ( opts[OPT_MAPSAMPLES] != 0 ) Mode |= MODE_MAPSAMPLES;
  136.  
  137.             if ( opts[OPT_SAVEINFO] != 0 ) Mode |= MODE_SAVEINFO;
  138.  
  139.             if ( opts[OPT_TRANSPOSE] != 0 ) Mode |= MODE_TRANSPOSE;
  140.  
  141.             if ( opts[OPT_VOLUMESHIFT] != 0 ) Mode |= MODE_VOLUMESHIFT;
  142.  
  143.             if ( opts[OPT_DRUMCHANNEL] != 0 )
  144.             {
  145.                 /* Drum channel is stored as value - 1 */
  146.                 DrumChann = *( (ULONG *)opts[OPT_DRUMCHANNEL] ) - 1;
  147.                 printf( "Drum channel set to: %d\n", DrumChann + 1 );
  148.             }
  149.  
  150.             if ( opts[OPT_TEMPOTYPE] != 0 )
  151.             {
  152.                 int value;
  153.  
  154.                 value = *( (ULONG *)opts[OPT_TEMPOTYPE] );
  155.  
  156.                 if ( value >= 0 && value <= 1 )
  157.                 {
  158.                     TempoType = value;
  159.                     printf( "Tempo type set to: %s\n", TempoTypes[TempoType] );
  160.                 }
  161.                 else printf( "Illegal value for TEMPO, using default of NORMAL\n" );
  162.             }
  163.  
  164.             FreeArgs ( RDArgs );
  165.  
  166.             /* Open the MID file */
  167.             if ( MidFN != NULL )
  168.             {
  169.                 r = OpenOut( MidFile, MidFN );
  170.             }
  171.  
  172.             /* Open the MOD file */
  173.             if ( r != NULL && ModFN != NULL )
  174.             {
  175.                 if ( ModFile->f != NULL ) SaveDefaults( Samples, ModFN ); // Save defaults
  176.  
  177.                 r = OpenIn( ModFile, ModFN );
  178.                 if ( r != NULL )
  179.                 {
  180.                     if ( !ReadModSpecs( ModFile, SongName, Samples ) )
  181.                         printf( "%s is not a .mod file\n", ModFN );
  182.                     else
  183.                     if ( !SetDefaults( Samples, ModFN ) ) CloseIn( ModFile );
  184.                 }
  185.             }
  186.  
  187.             if ( ( Mode & MODE_ABOUT ) == MODE_ABOUT )
  188.             {
  189.                 int i = 0;
  190.                 while ( MSG_ABOUT[i] != NULL ) printf( "%s\n", MSG_ABOUT[ i++ ] );
  191.  
  192.                 Mode = NULL; //Dont allow futher processing
  193.             }
  194.  
  195.             if ( ( Mode & MODE_MAPSAMPLES ) == MODE_MAPSAMPLES )
  196.             {
  197.                 if ( ModFile->f != NULL ) MapSamples( Samples );
  198.                 else
  199.                 printf( "%s", MSG_ERR_NO_MOD_FILENAME );
  200.             }
  201.  
  202.             if ( ( Mode & MODE_SAVEINFO ) == MODE_SAVEINFO )
  203.             {
  204.                 if ( ModFile->f != NULL ) SaveSamples( Samples );
  205.                 else
  206.                 printf( "%s", MSG_ERR_NO_MOD_FILENAME );
  207.             }
  208.  
  209.             if ( ( Mode & MODE_TRANSPOSE ) == MODE_TRANSPOSE )
  210.             {
  211.                 if ( ModFile->f != NULL ) Transpositions( Samples );
  212.                 else
  213.                 printf( "%s", MSG_ERR_NO_MOD_FILENAME );
  214.             }
  215.  
  216.             if ( ( Mode & MODE_VOLUMESHIFT ) == MODE_VOLUMESHIFT )
  217.             {
  218.                 if ( ModFile->f != NULL ) VolumeShifts( Samples );
  219.                 else
  220.                 printf( "%s", MSG_ERR_NO_MOD_FILENAME );
  221.             }
  222.  
  223.             /* Do the conversion */
  224.             if ( MidFile->f != NULL && ModFile->f != NULL && Mode != NULL )
  225.             {
  226.                 if ( ChooseChannels( Samples ) <= 16 )
  227.                 {
  228.                     ConvertMOD( ModFile, MidFile, SongName, Samples );
  229.                 }
  230.                 else
  231.                 printf( "Too many instruments, there is a maximum of 16 allowed\n" );
  232.             }
  233.             else
  234.             printf( "Both a source .MOD and a destination .MID file must be supplied\n" );
  235.  
  236.             /* If the file is open, close it */
  237.             if ( ModFile->f != NULL )
  238.             {
  239.                 CloseIn( ModFile );
  240.                 SaveDefaults( Samples, ModFN );
  241.             }
  242.  
  243.             /* If a filename has been allocated, free it */
  244.             if ( ModFN != NULL ) free( ModFN );
  245.  
  246.             /* If the file is open, close it */
  247.             if ( MidFile->f != NULL ) CloseOut( MidFile );
  248.  
  249.             /* If a filename has been allocated, free it */
  250.             if ( MidFN != NULL ) free( MidFN );
  251.         }
  252.         else printf( "Illegal parameters!\n" );
  253.     }
  254. }
  255.  
  256. /* Post: The byte b has been written to the buffer of the file f */
  257. void OutByte( bfile f, char b )
  258. {
  259.     if ( f->o == BUFFSIZE )
  260.     {
  261.         fwrite( f->b, 1, BUFFSIZE, f->f );
  262.         f->o = 0;
  263.   }
  264.  
  265.     f->b[ f->o++ ] = b;
  266. }
  267.  
  268. /* Pre: f was opened for writing */
  269. /* Post: The file f has has its buffer flushed */
  270. void FlushOut( bfile f )
  271. {
  272.     if ( f->o > 0 ) fwrite( f->b, 1, f->o, f->f );
  273.  
  274.     f->o = 0;
  275. }
  276.  
  277. /* Pre: f was opened for writing */
  278. /* Post: The file f has been flushed and is now closed */
  279. void CloseOut( bfile f )
  280. {
  281.     FlushOut( f );
  282.  
  283.     fclose( f->f );
  284.     f->f = NULL;
  285. }
  286.  
  287. /* Returns: NZ if the file f has been opened for writing with the name fn */
  288. int OpenOut( bfile f, string fn )
  289. {
  290.     if ( f->f != NULL ) CloseOut( f );
  291.  
  292.     f->f = fopen( fn, "wb" );
  293.     f->o = 0;
  294.  
  295.     return f->f != NULL;
  296. }
  297.  
  298. /* Returns: bfile-tell; the offset from the start */
  299. unsigned long Beatle( bfile f )
  300. {
  301.     return ftell( f->f ) + f->o;
  302. }
  303.  
  304. /* Pre: f was opened for reading */
  305. /* Returns: The next byte from the file f */
  306. unsigned char InByte( bfile f )
  307. {
  308.     if ( f->o == BUFFSIZE && !feof( f->f ) )
  309.     {
  310.         f->r = fread( f->b, 1, BUFFSIZE, f->f );
  311.         if ( f->r < BUFFSIZE ) f->b[ f->r ] = 0;
  312.  
  313.         f->o = 0;
  314.     }
  315.  
  316.     if ( f->o < f->r ) return f->b[ f->o++ ];
  317.  
  318.     return f->b[ f->o ];
  319. }
  320.  
  321. /* Post: The file f is now closed */
  322. void CloseIn( bfile f )
  323. {
  324.     fclose( f->f );
  325.     f->f = NULL;
  326. }
  327.  
  328. /* Returns: NZ if the file f has been opened for reading with the name fn */
  329. int OpenIn( bfile f, string fn )
  330. {
  331.     if ( f->f != NULL ) CloseIn( f );
  332.  
  333.     f->f = fopen( fn, "rb" );
  334.  
  335.     f->o = f->r = BUFFSIZE;
  336.  
  337.     return f->f != NULL;
  338. }
  339.  
  340. /* Pre: f was opened for reading */
  341. /* Post: f's file pointer has skipped forward n bytes */
  342. void Inskipp( bfile f, unsigned long n )
  343. {
  344.     n += f->o;
  345.  
  346.     while ( n >= BUFFSIZE && !feof( f->f ) )
  347.     {
  348.         f->r = fread( f->b, 1, BUFFSIZE, f->f );
  349.  
  350.         if ( f->r < BUFFSIZE ) f->b[ f->r ] = 0;
  351.  
  352.         n -= BUFFSIZE;
  353.     }
  354.     f->o = n; // May cause an error if was eof
  355. }
  356.  
  357. /* Returns: All necessary information regarding file f's status */
  358. struct bpos FPos( bfile f )
  359. {
  360.     struct bpos x;
  361.  
  362.     x.d = *f;
  363.     x.p = ftell( f->f );
  364.  
  365.     return x;
  366. }
  367.  
  368. /* Pre: x was the status of f previously */
  369. /* Post: File f has had its status changed to x */
  370. void FGoto( bfile f, struct bpos x )
  371. {
  372.     fseek( f->f, x.p, SEEK_SET );
  373.  
  374.     *f = x.d;
  375. }
  376.  
  377. /*
  378.  * Returns: # of bytes written after a variable-length-quantity equivalent
  379.  *    of i has been written to the file f.
  380.  */
  381. int WriteVLQ( bfile f, unsigned long i )
  382. {
  383.     int x = 0;
  384.     unsigned long buffer;
  385.  
  386.     buffer = i & 127;
  387.  
  388.     while ( (i >>= 7 ) > 0 )
  389.  
  390.     buffer = ( ( buffer << 8 ) | 128 ) + ( i & 127 );
  391.  
  392.     while ( 1 )
  393.     {
  394.         OutByte( f, buffer & 255 );
  395.         x++;
  396.         if ( buffer & 128 ) buffer >>= 8;
  397.         else return x;
  398.     }
  399. }
  400.  
  401. /* Returns: The number of samples in the Module file f */
  402. int MKTest( bfile f )
  403. {
  404.     unsigned long offset;
  405.     int i = 15;
  406.     char s[4];
  407.  
  408.     offset = ftell( f->f );
  409.  
  410.     if ( !fseek( f->f, 1080, SEEK_SET ) )
  411.     {
  412.         fread( s, 1, 4, f->f );
  413.  
  414.         if ( !memcmp( s, "M.K.", 4 ) || !memcmp( s, "M!K!", 4 ) ||
  415.             !memcmp( s, "FLT4", 4 ) ) i = 31;
  416.         else if ( !memcmp( s, "FLT8", 4 ) ) i = 0;
  417.     }
  418.  
  419.     fseek( f->f, offset, SEEK_SET );
  420.  
  421.     return i;
  422. }
  423.  
  424. /*
  425.  * Returns: A string similar to s, but has had any nasty headers removed
  426.  *    any leading spaces or trailing spaces, and all made lower-case with
  427.  *    any intermediate spaces replaced by underbar-characters
  428.  */
  429. string SimplifyName( string s )
  430. {
  431.     string t, r, x;
  432.  
  433.     x = strchr( s, ':' );
  434.  
  435.     if ( x != NULL && x - s == 5 && tolower( s[0] ) == 's' &&
  436.         tolower( s[1] ) == 't' && s[2] == '-' )
  437.     {
  438.         r = x = (string)malloc( 18 );
  439.         t = s + 6;
  440.  
  441.         while( *(x++) = *(t++) ); // Remove soundtracker header
  442.     } else strcpy( r = (string)malloc( 1 + strlen(s) ), s );
  443.  
  444.     for ( t = r; *t == ' '; t++ );
  445.  
  446.     x = r;
  447.  
  448.     while ( *(x++) = *(t++) ); // Remove leading spaces
  449.  
  450.     if ( *r )
  451.     {
  452.         x--;
  453.  
  454.         while ( *(--x) == ' ' ) // Remove trailing spaces
  455.  
  456.         *x = 0;
  457.     }
  458.  
  459.     /* Fill intermediate spaces with '_' */
  460.     for ( x = r; *x; x++ ) if ( *x == ' ' ) *x = '_';
  461.  
  462.     t = r = (string)realloc( r, strlen(r) + 1 );
  463.  
  464.     for ( ; *t; t++ ) *t = tolower( *t ); // Make the lot lower-case
  465.  
  466.     return r;
  467. }
  468.  
  469. /* Returns: Next line from file f, NULL on error/eof */
  470. string GetLine( FILE *f )
  471. {
  472.     string s, t;
  473.     int c;
  474.  
  475.     if ( ( t = s = (string)malloc( MAXSTRING ) ) == NULL )
  476.     {
  477.         printf( "%s", MSG_ERR_OUT_OF_MEMORY );
  478.         return NULL;
  479.     }
  480.  
  481.     while ( ( c = fgetc( f ) ) != EOF && c != '\n' ) *(t++) = c;
  482.  
  483.     if ( s == t )
  484.     {
  485.         free( s );
  486.         return NULL;
  487.     }
  488.  
  489.     *t = 0;
  490.  
  491.     return (string)realloc( s, t - s + 1 );
  492. }
  493.  
  494. /*
  495.  * Returns: Z if f is not a supported Amiga Module, else n is set to
  496.  * be the name of the Module and s is set to hold sample information
  497.  */
  498. int ReadModSpecs( bfile f, string n, samps s )
  499. {
  500.     unsigned char b, c;
  501.     int i, okmodule;
  502.     string t1;
  503.     samp *t2;
  504.  
  505.     for ( i = 20, t1 = n; i--; *(t1++) = InByte( f ) );
  506.  
  507.     okmodule = !*n || isprint( *n );
  508.     *t1 = 0;
  509.     c = s->n = MKTest( f );
  510.     okmodule = okmodule && c;
  511.  
  512.     for ( t2 = s->s; c--; t2++ )
  513.     {
  514.         for ( i = 22, t1 = t2->n; i--; *(t1++) = InByte( f ) );
  515.  
  516.         okmodule = okmodule && ( !*( t2->n ) || isprint( *(t2->n) ) );
  517.         *t1 = 0;
  518.         b = InByte( f );
  519.         t2->l = 256 * b + InByte( f );
  520.  
  521.         /* If the sample is this small, not worth processing */
  522.         if ( t2->l < 4 ) t2->l = 0;
  523.  
  524.         b = InByte( f );
  525.         t2->v = InByte( f );
  526.         InByte( f );
  527.         InByte( f );
  528.         b = InByte( f );
  529.  
  530.         /* Looping: plays 'forever' */
  531.         if ( 256 * b + InByte( f ) > 1 && t2->l ) t2->l = -1;
  532.  
  533.         t2->m = 0;
  534.     }
  535.  
  536.     return !feof( f->f ) && okmodule;
  537. }
  538.  
  539. /*
  540.  * Post: Sample data for ModFile has been scanned and samples in s have
  541.  * been given "reasonable" values for volume shifting and transpositions
  542.  * I hope :)
  543.  */
  544. void ScanSamples( samps s )
  545. {
  546.     samp *sam;
  547.     unsigned int maxpat = 0, i, j, k;
  548.     unsigned char x;
  549.     signed char c[SCANSIZE];
  550.     signed char max, min, *p;
  551.     unsigned long offset, len, lenarry[31];
  552.     long sum;
  553.     double ratio, junk;
  554.  
  555.     offset = ftell( ModFile->f );
  556.     fseek( ModFile->f, 42, SEEK_SET );
  557.  
  558.     for ( i = 0; i < s->n; i++ )
  559.     {
  560.         fread( &x, 1, 1, ModFile->f );
  561.         lenarry[i] = 256 * x;
  562.  
  563.         fread( &x, 1, 1, ModFile->f );
  564.         lenarry[i] += x;
  565.         lenarry[i] *= 2;
  566.  
  567.         fseek( ModFile->f, 28, SEEK_CUR );
  568.     }
  569.  
  570.     fseek( ModFile->f, 20 + 30 * s->n, SEEK_SET );
  571.     fread( &x, 1, 1, ModFile->f );
  572.     fread( c, 1, 129, ModFile->f );
  573.  
  574.     for ( ; x; x-- ) if ( c[x] > maxpat ) maxpat = c[x];
  575.  
  576.     len = 1024L * ( maxpat + 1 ) + 30 * s->n + ( ( s->n > 30 ) ? 4 : 0 ) + 150;
  577.  
  578.     fseek( ModFile->f, len, SEEK_SET );
  579.  
  580.     for ( i = 0, sam = s->s; i < s->n; i++, sam++ )
  581.     {
  582.         /* Set transposition values to 0 */
  583.         sam->t[0] = 0;
  584.         sam->t[1] = 0;
  585.         sam->t[2] = 0;
  586.         sam->a[0] = 0;
  587.  
  588.         /* No sample = no volume shifting */
  589.         if ( !sam->l )
  590.         {
  591.             sam->a[1] = 1;
  592.             sam->a[2] = 1;
  593.  
  594.             fseek( ModFile->f, lenarry[i], SEEK_CUR );
  595.         }
  596.         else
  597.         {
  598.             len = min( lenarry[i], SCANSIZE );
  599.  
  600.             if ( !( j = len = fread( c, 1, len, ModFile->f ) ) ) len = 1;
  601.  
  602.             fseek( ModFile->f, lenarry[i] - j, SEEK_CUR );
  603.  
  604.             min = 127;
  605.             max = -128;
  606.             sum = 0;
  607.  
  608.             for ( p = c; j--; p++ )
  609.             {
  610.                 sum += *p;
  611.  
  612.                 if ( *p > max ) max = *p;
  613.  
  614.                 if ( *p < min ) min = *p;
  615.             }
  616.  
  617.             /* Get average .. normally ~0 */
  618.             ratio = 1.0 * sum / len;
  619.  
  620.             if ( fabs( max - ratio ) > fabs( min - ratio ) )
  621.                 ratio = fabs( min - ratio ) / 64.0;
  622.             else
  623.                 ratio = fabs( max - ratio ) / 64.0;
  624.  
  625.             j = k = 1;
  626.  
  627.             /* Now find decent rational approx. */
  628.             while ( k++ < 15 )
  629.                 if ( fabs( modf( ratio * k, &junk ) - .5 ) > fabs( modf( ratio * j, &junk ) - .5 ) )
  630.                     j = k;
  631.  
  632.             if ( !( sam->a[1] = ratio * j + 0.5 ) )
  633.             {
  634.                 /* If really small scaling needed.. */
  635.                 sam->a[1] = 1;
  636.                 sam->a[2] = 16;
  637.             }
  638.             else sam->a[2] = j;
  639.         }
  640.     }
  641.  
  642.     fseek( ModFile->f, offset, SEEK_SET );
  643. }
  644.  
  645. /*
  646.  * Returns: NZ if the samples in s have been sucessfully allocated default
  647.  *    values corresponding to definitions in the DEF_MAPFILE file, and from
  648.  *    a .mm file corresponding to the filename fn
  649.  */
  650. int SetDefaults( samps s, string fn )
  651. {
  652.     FILE *f;
  653.     char i, m[MAXSTRING];
  654.     int d, e[6], v;
  655.     samp *sam;
  656.     string n, t;
  657.     bfile mmf;
  658.  
  659.     t = strchr( strcpy( m, fn ), '.' );
  660.  
  661.     if ( t == NULL )
  662.     {
  663.         i = strlen( m );
  664.         m[i] = '.';
  665.     }
  666.     else i = t - m;
  667.  
  668.     m[++i] = 'm';
  669.     m[++i] = 'm';
  670.     m[++i] = 0;
  671.     mmf->f = NULL;
  672.  
  673.     if ( OpenIn( mmf, m ) )
  674.     {
  675.         for ( i = s->n, sam = s->s; i--; sam++ )
  676.         {
  677.             sam->m = InByte( mmf );
  678.             sam->t[0] = (signed char)InByte( mmf );
  679.             sam->t[1] = (signed char)InByte( mmf );
  680.             sam->t[2] = (signed char)InByte( mmf );
  681.             sam->a[0] = (signed char)InByte( mmf );
  682.             sam->a[1] = (signed char)InByte( mmf );
  683.             sam->a[2] = (signed char)InByte( mmf );
  684.         }
  685.  
  686.         CloseIn( mmf );
  687.     }
  688.     else ScanSamples( s );
  689.  
  690.     if ( ( f = fopen( DEF_MAPFILE, "rt" ) ) == NULL )
  691.     {
  692.         printf( "%s: Not found\n", DEF_MAPFILE );
  693.         return 0;
  694.     }
  695.  
  696.     i = s->n;
  697.     for ( sam = s->s; i--; sam++ )
  698.     if ( sam->l )
  699.     {
  700.         n = SimplifyName( sam->n );
  701.         t = GetLine( f );
  702.         e[3] = 0; // These are the default volume constants
  703.         e[4] = 1;
  704.         e[5] = 1;
  705.         sscanf( t, "%s %d %d %d %d %d %d %d", m, &d, &e[0], &e[1], &e[2], &e[3], &e[4], &e[5] );
  706.  
  707.         if ( ( v = strcmp( m, n ) ) > 0 )
  708.         {
  709.             rewind( f );
  710.             free( t );
  711.             t = GetLine( f );
  712.             e[3] = 0;
  713.             e[4] = 1;
  714.             e[5] = 1;
  715.             sscanf( t, "%s %d %d %d %d %d %d %d", m, &d, &e[0], &e[1], &e[2], &e[3], &e[4], &e[5] );
  716.             v = strcmp( m, n );
  717.         }
  718.  
  719.         free( t );
  720.  
  721.         while ( v < 0 && ( t = GetLine( f ) ) != NULL )
  722.         {
  723.             e[3] = 0;
  724.             e[4] = 1;
  725.             e[5] = 1;
  726.             sscanf( t, "%s %d %d %d %d %d %d %d", m, &d, &e[0], &e[1], &e[2], &e[3], &e[4], &e[5] );
  727.             free( t );
  728.             v = strcmp( m, n );
  729.         }
  730.  
  731.         if ( !v )
  732.         {
  733.             sam->m = d;
  734.             sam->t[0] = e[0];
  735.             sam->t[1] = e[1];
  736.             sam->t[2] = e[2];
  737.             sam->a[0] = e[3];
  738.             sam->a[1] = e[4];
  739.             sam->a[2] = e[5];
  740.         }
  741.  
  742.         free( n );
  743.     }
  744.  
  745.     fclose( f );
  746.     return 1;
  747. }
  748.  
  749. /*
  750.  * Post: The samples attributes in s have been written to a .mm file
  751.  *   corresponding to the filename fn
  752.  */
  753. void SaveDefaults( samps s, string fn )
  754. {
  755.     char m[MAXSTRING];
  756.     string t;
  757.     char i;
  758.     bfile mmf;
  759.     samp *sam;
  760.  
  761.     t = strchr( strcpy( m, fn ), '.' );
  762.  
  763.     if ( t == NULL )
  764.     {
  765.         i = strlen( m );
  766.         m[i] = '.';
  767.     }
  768.     else i = t - m;
  769.  
  770.     m[++i] = 'm';
  771.     m[++i] = 'm';
  772.     m[++i] = 0;
  773.     mmf->f = NULL;
  774.  
  775.     if ( !OpenOut( mmf, m ) ) return;
  776.  
  777.     for ( i = s->n, sam = s->s; i--; sam++ )
  778.     {
  779.         OutByte( mmf, sam->m );
  780.         OutByte( mmf, sam->t[0] );
  781.         OutByte( mmf, sam->t[1] );
  782.         OutByte( mmf, sam->t[2] );
  783.         OutByte( mmf, sam->a[0] );
  784.         OutByte( mmf, sam->a[1] );
  785.         OutByte( mmf, sam->a[2] );
  786.     }
  787.  
  788.     CloseOut( mmf );
  789. }
  790.  
  791. /* Post: The NULL-terminated array sp is gone */
  792. void NullArryFree( string *sp )
  793. {
  794.     string *t;
  795.  
  796.     t = sp;
  797.  
  798.     while ( *t != NULL ) free( *(t++) );
  799.  
  800.     free( sp );
  801. }
  802.  
  803. /* Returns: MIDI instrument selected from file DEF_INSFILE */
  804. int Instrument( void )
  805. {
  806.     static int w = 0, doff = -1;
  807.     static string *sp = NULL;
  808.     int c;
  809.  
  810.     if ( sp == NULL )
  811.     {
  812.         FILE *f;
  813.         string *t, s;
  814.         int x, i = 1;
  815.  
  816.         if ( ( f = fopen( DEF_INSFILE, "rt" ) ) == NULL )
  817.         {
  818.             printf( "%s: Not found\n", DEF_INSFILE );
  819.             return -1;
  820.         }
  821.  
  822.         if ( ( t = sp = (string *)malloc( 257 * sizeof( string ) ) ) == NULL )
  823.         {
  824.             printf( "%s", MSG_ERR_OUT_OF_MEMORY );
  825.             return -1;
  826.         }
  827.  
  828.         while ( ( s = GetLine( f ) ) != NULL )
  829.  
  830.         if ( x = strlen( s ) ) // Ignore blank lines
  831.         {
  832.             i++;
  833.  
  834.             if ( x > w ) w = x;
  835.  
  836.             *(t++) = s;
  837.  
  838.             /* Take note of first drum position */
  839.             if ( doff < 0 && *s == 'D' ) sscanf( s, "D%d ", &doff );
  840.         }
  841.  
  842.         *t = NULL;
  843.         sp = (string *)realloc( sp, i * sizeof( string ) ); // i <= 257
  844.  
  845.         fclose( f );
  846.     }
  847.  
  848.     c = 0;
  849.     c = ScrollChoice( "MIDI Instruments", sp, w );
  850.     if ( c > 127 ) c += doff;
  851.  
  852.     return c;
  853. }
  854.  
  855. /* Returns: a string representing the MIDI instrument *sam */
  856. string MIDIVal( samp *sam )
  857. {
  858.     string s;
  859.  
  860.     s = (string)malloc( 5 );
  861.  
  862.     if ( sam->m < 128 ) sprintf( s, "%4d", sam->m );
  863.     else sprintf( s, "D%3d", sam->m - 128 );
  864.  
  865.     return s;
  866. }
  867.  
  868. /* Returns: a string representing the transpose amount of *sam */
  869. string TransVal( samp *sam )
  870. {
  871.     string s;
  872.  
  873.     s = (string)malloc( 15 );
  874.  
  875.     if ( !sam->t[1] ) sprintf( s, "          %4d", sam->t[0] );
  876.     else
  877.     if ( !sam->t[2] ) sprintf( s, "     %4d,%4d", sam->t[0], sam->t[1] );
  878.     else sprintf( s, "%4d,%4d,%4d", sam->t[0], sam->t[1], sam->t[2] );
  879.  
  880.     return s;
  881. }
  882.  
  883. /* Returns: a string representing the volume shifting formula for *sam */
  884. string VolumeVal( samp *sam )
  885. {
  886.     string s;
  887.  
  888.     s = (string)malloc( 17 );
  889.  
  890.     if ( sam->a[0] < 0 )
  891.         sprintf( s, "(? -%3d)*%3d/%3d", abs(sam->a[0]), sam->a[1], sam->a[2] );
  892.     else
  893.         sprintf( s, "(? +%3d)*%3d/%3d", sam->a[0], sam->a[1], sam->a[2] );
  894.  
  895.     return s;
  896. }
  897.  
  898. /* Returns: an empty string */
  899. string NullVal( samp *sam )
  900. {
  901.     string s;
  902.  
  903.     *( s = (string)malloc( 1 ) ) = 0;
  904.  
  905.     return s;
  906. }
  907.  
  908. /* Returns: Sample selected from list of samples, -1 on error */
  909. int Sample( samps s, string (*MIDIVal)(samp *x), int w )
  910. {
  911.     string *sp, *t, p;
  912.     samp *sam;
  913.     int i;
  914.  
  915.     if ( ( t = sp = (string *)malloc( ( s->n + 1 ) * sizeof( string ) ) ) == NULL )
  916.     {
  917.         printf( "%s", MSG_ERR_OUT_OF_MEMORY );
  918.         return -1;
  919.     }
  920.  
  921.     for ( i = s->n, sam = s->s; i--; sam++ )
  922.     {
  923.         *t = (string)malloc( 25 + w );
  924.         p = MIDIVal( sam );
  925.  
  926.         sprintf( *t, "%c%-22s %s", (sam->l) ? '*' : ' ', sam->n, p );
  927.         free( p );
  928.         t++;
  929.     }
  930.  
  931.     *t = NULL;
  932.     i = ScrollChoice( "Select Sample", sp, 24 + w );
  933.     NullArryFree( sp );
  934.  
  935.     return i;
  936. }
  937.  
  938. /*
  939.  * Returns: The number of different channels needed to play instruments. If
  940.  *    that number is not greater than 16, upto 16 channels will be allocated
  941.  *    to the samples.
  942.  */
  943. int ChooseChannels( samps s )
  944. {
  945.     unsigned char c, d = 0, i[128], m, n, numchan;
  946.     samp *sam1, *sam2;
  947.  
  948.     n = s->n;
  949.     sam1 = s->s;
  950.     memset( i, 0, 128 );
  951.  
  952.     for ( n = s->n, sam1 = s->s; n--; sam1++ )
  953.     {
  954.         sam1->c = -1;
  955.         if ( sam1->l )
  956.             if ( sam1->m > 127 )
  957.             {
  958.                 d = 1;
  959.                 sam1->c = DrumChann;
  960.             }
  961.             else i[ sam1->m ] = 1;
  962.         else sam1->m = 0;
  963.     }
  964.  
  965.     for ( numchan = d, n = 128; n--; numchan += i[n] );
  966.  
  967.     if ( numchan > 16 ) return numchan;
  968.  
  969.     /* Ok.. now we must go through and set channels appropriately */
  970.     m = s->n;
  971.     sam1 = s->s;
  972.     c = 0;
  973.     while ( m-- )
  974.     {
  975.         if ( sam1->c < 0 )
  976.         {
  977.             sam1->c = c;
  978.             n = m;
  979.             sam2 = sam1 + 1;
  980.  
  981.             while ( n-- )
  982.             {
  983.                 if ( sam2->c < 0 )
  984.                     if ( sam2->m == sam1->m || ! sam2->l ) sam2->c = c;
  985.                 sam2++;
  986.             }
  987.  
  988.             if ( ++c == DrumChann && d )
  989.             c++;
  990.         }
  991.  
  992.         sam1++;
  993.     }
  994.  
  995.     return numchan;
  996. }
  997.  
  998. /* Post: The samples s have been allocated appropriate instruments, we hope */
  999. void MapSamples( samps s )
  1000. {
  1001.     int i, j;
  1002.  
  1003.     do
  1004.         if ( ( i = Sample( s, MIDIVal, 4 ) ) >= 0 && ( j = Instrument() ) >= 0 )
  1005.             s->s[i].m = j;
  1006.     while ( i>=0 );
  1007. }
  1008.  
  1009. /* Post: The sample sam has been updated in the DEF_MAPFILE file */
  1010. void SaveSamp( samp sam )
  1011. {
  1012.     FILE *f1, *f2;
  1013.     string s, n;
  1014.     int v, d;
  1015.     char m[MAXSTRING];
  1016.  
  1017.     if ( !sam.l ) return;
  1018.  
  1019.     if ( ( f1 = fopen( DEF_MAPFILE, "rt" ) ) == NULL )
  1020.     {
  1021.         printf( "%s: Not found\n", DEF_MAPFILE );
  1022.         return;
  1023.     }
  1024.  
  1025.     f2 = fopen( "temp.$$$", "wt" );
  1026.     n = SimplifyName( sam.n );
  1027.     v = 1;
  1028.  
  1029.     while ( v > 0 && ( s = GetLine( f1 ) ) != NULL )
  1030.     {
  1031.         sscanf( s, "%s %d", m, &d );
  1032.  
  1033.         if ( ( v = strcmp( n, m ) ) <= 0 )
  1034.         {
  1035.             fprintf( f2, "%s %d %d %d %d %d %d %d\n", n, sam.m, sam.t[0], sam.t[1], sam.t[2], sam.a[0], sam.a[1], sam.a[2] );
  1036.  
  1037.             free( n );
  1038.             n = NULL;
  1039.  
  1040.             if ( v ) fprintf( f2, "%s\n", s );
  1041.         }
  1042.         else fprintf( f2, "%s\n", s );
  1043.         free( s );
  1044.     }
  1045.  
  1046.     while ( ( s = GetLine( f1 ) ) != NULL )
  1047.     {
  1048.         fprintf( f2, "%s\n", s );
  1049.         free( s );
  1050.     }
  1051.  
  1052.     if ( n != NULL )
  1053.     {
  1054.         fprintf( f2, "%s %d %d %d %d %d %d %d\n", n, sam.m, sam.t[0], sam.t[1], sam.t[2], sam.a[0], sam.a[1], sam.a[2] );
  1055.         free( n );
  1056.     }
  1057.  
  1058.     fclose( f2 );
  1059.     fclose( f1 );
  1060.  
  1061.     if ( unlink( DEF_MAPFILE ) < 0 || rename( "temp.$$$", DEF_MAPFILE ) < 0 )
  1062.         printf( "File %s cannot be updated. Instrument map changes cannot be made\n" );
  1063. }
  1064.  
  1065. /* Post: The desired sample attributes of s have been saved to disk */
  1066. void SaveSamples( samps s )
  1067. {
  1068.     int i;
  1069.  
  1070.     do
  1071.         if ( ( i = Sample( s, NullVal, 0 ) ) >= 0 ) SaveSamp( s->s[i] );
  1072.     while ( i >= 0 );
  1073. }
  1074.  
  1075. /* Post: All necessary transpositions have been applied to the samples s */
  1076. void Transpositions( samps s )
  1077. {
  1078.     int i;
  1079.  
  1080.     do
  1081.     if ( ( i = Sample( s, TransVal, 14 ) ) >= 0 )
  1082.     {
  1083.         char s1[41];
  1084.         string s2;
  1085.         samp *sam;
  1086.  
  1087.         sam = s->s + i;
  1088.  
  1089.         if ( !sam->t[1] ) sprintf( s1, "%d", sam->t[0] );
  1090.         else
  1091.         if ( !sam->t[2] ) sprintf( s1, "%d,%d", sam->t[0], sam->t[1] );
  1092.         else sprintf( s1, "%d,%d,%d", sam->t[0], sam->t[1], sam->t[2] );
  1093.  
  1094.         s2 = (string)malloc( 10 );
  1095.         strcpy( s2, "0,1,1" );
  1096.         s2 = DialogBox( MSG_ENTER_TRANSPOSITION, s1 );
  1097.  
  1098.         sam->t[1] = 0;
  1099.         sam->t[2] = 0;
  1100.  
  1101.         sscanf( s2, "%d,%d,%d", &sam->t[0], &sam->t[1], &sam->t[2] );
  1102.         free( s2 );
  1103.  
  1104.         if ( ( sam->t[0] || sam->t[1] ) && sam->m > 127 )
  1105.             printf( "Warning: transposition value for percussion instrument is changed\n" );
  1106.  
  1107.         if ( sam->t[0] <- 128 || sam->t[0] > 127 || sam->t[1] < -128 ||
  1108.          sam->t[1] > 127 || sam->t[2] <- 128 || sam->t[2] > 127 )
  1109.         {
  1110.             printf( "Warning: Transposition value out of range, resetting to 0\n" );
  1111.             sam->t[0] = 0;
  1112.             sam->t[1] = 0;
  1113.             sam->t[2] = 0;
  1114.         }
  1115.     }
  1116.     while ( i >= 0 );
  1117. }
  1118.  
  1119. /* Post: All volume shifting formulae have been defined for the samples s */
  1120. void VolumeShifts( samps s )
  1121. {
  1122.     int i;
  1123.  
  1124.     do
  1125.     {
  1126.         i = Sample( s, VolumeVal, 16 );
  1127.  
  1128.         if ( i >= 0 )
  1129.         {
  1130.             char s1[41];
  1131.             string s2;
  1132.             samp *sam;
  1133.  
  1134.             sam = s->s + i;
  1135.             sprintf( s1, "%d,%d,%d", sam->a[0], sam->a[1], sam->a[2] );
  1136.  
  1137.             s2 = (string)malloc( 10 );
  1138.             s2 = DialogBox( MSG_ENTER_VOLUMESHIFT, s1 );
  1139.  
  1140.             if ( sscanf( s2, "%d,%d,%d", &sam->a[0], &sam->a[1], &sam->a[2]) != 3 ||
  1141.                 sam->a[0] > 127 || sam->a[0] < -128 || sam->a[1] > 127 ||
  1142.                 sam->a[1] < 0 || sam->a[2] > 127 || sam->a[2] < 1 )
  1143.             {
  1144.                 printf( "Warning: volume-shift values out of range, resetting to 0, 1, 1\n" );
  1145.                 sam->a[0] = 0;
  1146.                 sam->a[1] = 1;
  1147.                 sam->a[2] = 1;
  1148.             }
  1149.  
  1150.             free( s2 );
  1151.         }
  1152.     }
  1153.     while ( i >= 0 );
  1154. }
  1155.  
  1156. /* Returns: MIDI note equivalent of MOD period-lengths */
  1157. unsigned char NoteValue( unsigned int n )
  1158. {
  1159.     static unsigned int t[72] =
  1160.     {
  1161.         1712, 1616, 1525, 1440, 1357, 1281, 1209, 1141, 1077, 1017, 961, 907,
  1162.         856, 808, 762, 720, 678, 640, 604, 570, 538, 508, 480, 453,
  1163.         428, 404, 381, 360, 339, 320, 302, 285, 269, 254, 240, 226,
  1164.         214, 202, 190, 180, 170, 160, 151, 143, 135, 127, 120, 113,
  1165.         107, 101, 95, 90, 85, 80, 76, 71, 67, 64, 60, 57,
  1166.         53, 50, 48, 45, 42, 40, 38, 36, 34, 32, 30, 28
  1167.     };
  1168.  
  1169.     signed char a = 0, m = 35, b = 71;
  1170.  
  1171.     if ( !n ) return 0;
  1172.  
  1173.     /* Binary search */
  1174.     for ( ; b-a > 1; m = ( a + b ) / 2 )
  1175.     if ( t[m] < n ) b = m;
  1176.     else a = m;
  1177.  
  1178.     /* Choose closest value */
  1179.     if ( n - t[b] < t[a] - n ) return (unsigned char)( b + 36 );
  1180.  
  1181.     return (unsigned char )( a + 36 );
  1182. }
  1183.  
  1184. /* Returns: # of ticks to play note length l at pitch n, b beats/min */
  1185. unsigned long NoteLength( unsigned char n, unsigned int l, unsigned int b )
  1186. {
  1187.     static float t[84] =
  1188.     {
  1189.         3.200e-3, 3.020e-3, 2.851e-3, 2.691e-3, 2.540e-3, 2.397e-3,
  1190.         2.263e-3, 2.136e-3, 2.016e-3, 1.903e-3, 1.796e-3, 1.695e-3,
  1191.         1.600e-3, 1.510e-3, 1.425e-3, 1.345e-3, 1.270e-3, 1.197e-3,
  1192.         1.131e-3, 1.068e-3, 1.008e-3, 9.514e-4, 8.980e-4, 8.476e-4,
  1193.         8.000e-4, 7.551e-4, 7.127e-4, 6.727e-4, 6.350e-4, 5.993e-4,
  1194.         5.657e-4, 5.339e-4, 5.040e-4, 4.757e-4, 4.490e-4, 4.238e-4,
  1195.         4.000e-4, 3.775e-4, 3.564e-4, 3.364e-4, 3.175e-4, 2.997e-4,
  1196.         2.828e-4, 2.670e-4, 2.520e-4, 2.378e-4, 2.245e-4, 2.119e-4,
  1197.         2.000e-4, 1.888e-4, 1.782e-4, 1.682e-4, 1.587e-4, 1.498e-4,
  1198.         1.414e-4, 1.335e-4, 1.260e-4, 1.189e-4, 1.122e-4, 1.059e-4,
  1199.         1.000e-4, 9.439e-5, 8.909e-5, 8.409e-5, 7.937e-5, 7.492e-5,
  1200.         7.071e-5, 6.674e-5, 6.300e-5, 5.946e-5, 5.612e-5, 5.297e-5,
  1201.         5.000e-5, 4.719e-5, 4.454e-5, 4.204e-5, 3.969e-5, 3.746e-5,
  1202.         3.536e-5, 3.337e-5, 3.150e-5, 2.973e-5, 2.806e-5, 2.649e-5
  1203.     }; /* Multipliers for each pitch: 12th roots of 2 apart */
  1204.  
  1205.     /* Better not slide out of this range */
  1206.     return (unsigned long)( t[n - 36] * b * l );
  1207. }
  1208.  
  1209. /* Post: The MIDI header has been written to mf, with #tracks = n */
  1210. void WriteHeader( bfile mf, unsigned char n )
  1211. {
  1212.     static unsigned char MIDIH[14] =
  1213.     {
  1214.         77, 84, 104, 100, 0, 0, 0, 6, 0, 1, 0, (unsigned char)-1, 0, 192
  1215.     };
  1216.  
  1217.     int i = 0;
  1218.  
  1219.     MIDIH[11] = n + 1;
  1220.  
  1221.     while ( i < 14 )
  1222.  
  1223.     OutByte( mf, MIDIH[i++] );
  1224. }
  1225.  
  1226. /*
  1227.  * Returns: the number of bytes written as track 0 so far, given mf as the
  1228.  *    output MIDI file. s is the name of the tune.
  1229.  */
  1230. unsigned int Trk0Info( bfile mf, string s )
  1231. {
  1232.     static unsigned char TRK0I[63] =
  1233.     {
  1234.         0, 255, 2, 42, 70, 105, 108, 101, 32, 67, 111, 112, 121, 114, 105, 103,
  1235.         104, 116, 32, 40, 99, 41, 32, 49 ,57, 57, 51, 32, 65, 100, 114, 101, 110,
  1236.         97, 108, 105, 110, 32, 83, 111, 102, 116, 119, 97, 114, 101,
  1237.         0, 255, 88, 4, 3, 2, 24, 8,
  1238.         0, 255, 89, 2, 0, 0,
  1239.         0, 255, 3
  1240.     }; /* Standard header + copyright message */
  1241.  
  1242.     unsigned int i = 0;
  1243.  
  1244.     while ( i < 63 ) OutByte( mf, TRK0I[i++] );
  1245.  
  1246.     i = 64 + strlen( s );
  1247.  
  1248.     OutByte( mf, strlen( s ) );
  1249.  
  1250.     while ( *s ) OutByte( mf, *(s++) );
  1251.  
  1252.     return i;
  1253. }
  1254.  
  1255. /* Post: a (file position) and b (number) have been added to the log */
  1256. void AddToLog( unsigned long a, unsigned long b )
  1257. {
  1258.     PosLog[ PosI++ ] = b;
  1259.     PosLog[ PosI++ ] = a;
  1260. }
  1261.  
  1262. /* Post: PosLog has been written into file f */
  1263. void WriteLog( FILE *f )
  1264. {
  1265.     unsigned long x, y;
  1266.     unsigned char c[4];
  1267.  
  1268.     if ( !PosI ) return;
  1269.  
  1270.     x = ftell( f );
  1271.  
  1272.     while ( PosI )
  1273.     {
  1274.         fseek( f, PosLog[ --PosI ], SEEK_SET );
  1275.  
  1276.         y = PosLog[ --PosI ];
  1277.  
  1278.         c[3] = y & 255;
  1279.         y >>= 8;
  1280.         c[2] = y & 255;
  1281.         y >>= 8;
  1282.         c[1] = y & 255;
  1283.         y >>= 8;
  1284.         c[0] = y;
  1285.         fwrite( c, 1, 4, f );
  1286.     }
  1287.  
  1288.     fseek( f, x, SEEK_SET );
  1289. }
  1290.  
  1291. /* Returns: A volume in the range 0..127 */
  1292. unsigned char RestrictVol( int v )
  1293. {
  1294.     if ( v < 0 ) return 0;
  1295.     else return (unsigned char)( ( v > 127 ) ? 127 : v );
  1296. }
  1297.  
  1298. /*
  1299.  * Post: The Amiga MODfile f1 has been converted and written to MIDI file f2,
  1300.  *    using instrument mappings smp. Tune has a name tn.
  1301.  */
  1302. void ConvertMOD( bfile f1, bfile f2, string tn, samps smp )
  1303. {
  1304.     unsigned char b, length, pattern[128];
  1305.     string n;
  1306.     unsigned int i, j, k, tempdone = 0;
  1307.     samp *sam;
  1308.     struct bpos p1, p2;
  1309.  
  1310.     p1 = FPos( f1 );
  1311.     length = InByte( f1 );
  1312.     InByte( f1 );
  1313.  
  1314.     for ( i = 0; i < 128; pattern[i++] = InByte( f1 ) );
  1315.  
  1316.     Inskipp( f1, ( smp->n > 15 ) ? 4 : 0 );
  1317.     WriteHeader( f2, smp->n );
  1318.     p2 = FPos( f1 );
  1319.  
  1320.     for ( i = 0, sam = smp->s - 1; i <= smp->n; sam++, i++ )
  1321.     {
  1322.         unsigned long cnt, inst, timer, delay[4];
  1323.         unsigned char c;
  1324.  
  1325.         OutByte( f2, 77 );
  1326.         OutByte( f2, 84 );
  1327.         OutByte( f2, 114 );
  1328.         OutByte( f2, 107 );
  1329.  
  1330.         inst = Beatle( f2 ); /* Store this position so can set AFTERWARDS */
  1331.  
  1332.         OutByte( f2, 0 );
  1333.         OutByte( f2, 0 );
  1334.         OutByte( f2, 0 );
  1335.         OutByte( f2, 0 );
  1336.  
  1337.         if ( !i ) cnt = Trk0Info( f2, tn );
  1338.         else
  1339.         {
  1340.         OutByte( f2, 0 );
  1341.         OutByte( f2, (unsigned char)255 );
  1342.         OutByte( f2, 3 );
  1343.  
  1344.         b = strlen( n = sam->n );
  1345.  
  1346.         OutByte( f2, b );
  1347.  
  1348.         cnt = 7 + b;
  1349.  
  1350.         while ( b-- ) OutByte( f2, *(n++) );
  1351.  
  1352.         c = sam->c;
  1353.  
  1354.         OutByte( f2, 0 );
  1355.         OutByte( f2, 0xC0 + c ); // Set channel
  1356.         OutByte( f2, ( sam->m > 127 ) ? 126 : sam->m );
  1357.     }
  1358.  
  1359.     timer = 0;
  1360.  
  1361.     if ( sam->l || !i )
  1362.     {
  1363.         unsigned int bpm, ticks, l, effect, h;
  1364.         unsigned char sampnum, lastsam[4] = { 0 }, vol[4];
  1365.         signed char patbreak;
  1366.         unsigned long x, pause;
  1367.         int note, lastslide, slideto;
  1368.         int n[4][48][2]; // Note data for a song position
  1369.         int lastn[4]; // Last note on a particular channel
  1370.  
  1371.         printf( "Converting sample %d\n", i );
  1372.  
  1373.         memset( lastn, 0, 4 * sizeof( int ) );
  1374.         memset( vol, 0, 4 );
  1375.         memset( delay, 0, 4 * sizeof( long ) );
  1376.  
  1377.         bpm = 125;
  1378.         ticks = 6;
  1379.         lastslide = slideto = 0;
  1380.         patbreak = 0;
  1381.  
  1382.         for ( h = 48; h--; )
  1383.         for ( k = 4; k--; )
  1384.             n[k][h][0] = 0;
  1385.             for ( l = 0; l < length; l++ )
  1386.             {
  1387.                 if ( pattern[l] <= pattern[ l - 1 ] || !l )
  1388.                 {
  1389.                     FGoto( f1, p2 );
  1390.                     x = (unsigned)1024 * pattern[l];
  1391.                 }
  1392.                 else x = (unsigned)1024 * ( pattern[l] - pattern[ l - 1 ] - 1 );
  1393.  
  1394.                 Inskipp( f1, x );
  1395.                 j = 64;
  1396.  
  1397.                 if ( patbreak > 0 ) patbreak = 1 - patbreak;
  1398.  
  1399.                 while ( j-- )
  1400.                 {
  1401.                     pause = 0;
  1402.  
  1403.                     if ( patbreak ) Inskipp( f1, 16 );
  1404.                     else
  1405.                     for ( k = 0; k < 4; k++ )
  1406.                     {
  1407.                         n[k][0][1] = sam->v;
  1408.                         sampnum = InByte( f1 );
  1409.                         note = ( ( sampnum & 15 ) << 8 ) + InByte( f1 );
  1410.                         effect = InByte( f1 );
  1411.                         sampnum = ( sampnum & ~15 ) + ( effect >> 4 );
  1412.  
  1413.                         if ( !i ) note = 0;
  1414.  
  1415.                         if ( ( note || sampnum ) && delay[k] )
  1416.                         {
  1417.                             /* Stop old note */
  1418.                             cnt += 3 + WriteVLQ( f2, timer );
  1419.                             timer = 0;
  1420.  
  1421.                             OutByte( f2, 0x80 + c ); // Note off
  1422.                             OutByte( f2, ENOTE( lastn[k], 0 ) );
  1423.                             OutByte( f2, RestrictVol( EVOL( vol[k] ) ) );
  1424.  
  1425.                             if ( sam->t[1] )
  1426.                             {
  1427.                                 cnt += 4;
  1428.  
  1429.                                 OutByte( f2, 0 );
  1430.                                 OutByte( f2, 0x80 + c );
  1431.                                 OutByte( f2, ENOTE( lastn[k], 1 ) );
  1432.                                 OutByte( f2, RestrictVol( EVOL( vol[k] ) ) );
  1433.  
  1434.                                 if ( sam->t[2] )
  1435.                                 {
  1436.                                     cnt += 4;
  1437.  
  1438.                                     OutByte( f2, 0 );
  1439.                                     OutByte( f2, 0x80 + c );
  1440.                                     OutByte( f2, ENOTE( lastn[k], 2 ) );
  1441.                                     OutByte( f2, RestrictVol( EVOL( vol[k] ) ) );
  1442.                                 }
  1443.                             }
  1444.                             delay[k] = 0;
  1445.                         }
  1446.  
  1447.                         /* Check "defaults" */
  1448.                         if ( !note && sampnum == i ) note = lastn[k];
  1449.                         else
  1450.                         if ( !sampnum )
  1451.                             if ( lastsam[k] == i ) sampnum = i;
  1452.                             else note = 0;
  1453.                         else
  1454.                         {
  1455.                             if ( sampnum != i ) note = 0;
  1456.                             lastsam[k] = sampnum;
  1457.                         }
  1458.  
  1459.                         n[k][0][0] = note;
  1460.                         effect = ( ( effect & 15 ) << 8 ) + InByte( f1 );
  1461.  
  1462.                         switch ( effect & 0xF00 )
  1463.                         {
  1464.                             /* Arpeggio */
  1465.                             case 0x000:
  1466.                                 {
  1467.                                     int nv;
  1468.  
  1469.                                     if ( !i || !effect || sam->m > 127 ) break;
  1470.                                     if ( !note )
  1471.                                         if ( !delay[k] ) break;
  1472.                                         else
  1473.                                         {
  1474.                                             nv = NoteValue( lastn[k] );
  1475.                                             n[k][47][0] = lastn[k];
  1476.                                             n[k][47][1] = vol[k];
  1477.  
  1478.                                             if ( effect & 0x0F0 ) n[k][16][0] = -( nv + ( ( effect & 0x0F0 ) >> 4 ) );
  1479.                                             n[k][16][1] = vol[k];
  1480.  
  1481.                                             if ( effect & 0x00F ) n[k][32][0] = -( nv + ( effect & 0x00F ) );
  1482.                                             n[k][32][1] = vol[k];
  1483.                                         }
  1484.                                     else
  1485.                                     {
  1486.                                         nv = NoteValue( note );
  1487.                                         n[k][47][0] = note;
  1488.                                         n[k][47][1] = sam->v;
  1489.  
  1490.                                         if ( effect & 0x0F0 ) n[k][16][0] = -( nv + ( ( effect & 0x0F0 ) >> 4 ) );
  1491.                                         n[k][16][1] = sam->v;
  1492.  
  1493.                                         if ( effect & 0x00F ) n[k][32][0] = -( nv + ( effect & 0x00F ) );
  1494.                                         n[k][32][1] = sam->v;
  1495.                                     }
  1496.                                 break;
  1497.                             }
  1498.  
  1499.                         /* Slide to */
  1500.                         case 0x300:
  1501.                             if ( !note && !slideto || note == lastn[k] || sam->m > 127 ) break;
  1502.  
  1503.                             if ( effect & 0x0FF ) lastslide = effect & 0x0FF;
  1504.                             else lastslide = abs( lastslide );
  1505.  
  1506.                             if ( note ) slideto = note;
  1507.  
  1508.                             if ( slideto > lastn[k] )
  1509.                             {
  1510.                                 n[k][0][0] = lastn[k] + lastslide*( ticks - 1 );
  1511.                                 if ( n[k][0][0] > 856 ) n[k][0][0] = 856;
  1512.  
  1513.                                 if ( n[k][0][0] > slideto ) n[k][0][0] = slideto;
  1514.                             }
  1515.                             else
  1516.                             {
  1517.                                 n[k][0][0] = lastn[k] - lastslide * ( ticks - 1 );
  1518.                                 if ( n[k][0][0] < 113 ) n[k][0][0] = 113;
  1519.  
  1520.                                 if ( n[k][0][0] < slideto ) n[k][0][0] = slideto;
  1521.                             }
  1522.  
  1523.                             n[k][0][1] = vol[k];
  1524.                         break;
  1525.  
  1526.                         /* Slide up */
  1527.                         case 0x100:
  1528.                         /* Slide down */
  1529.                         case 0x200:
  1530.                             if ( ! ( effect & 0x0FF ) || sam->m > 127 ) break;
  1531.  
  1532.                             if ( effect & 0x200 ) lastslide = effect & 0x0FF;
  1533.                             else lastslide = -( effect & 0x0FF );
  1534.  
  1535.                             if ( !note )
  1536.                                 if ( !delay[k] ) break;
  1537.                                 else
  1538.                                 {
  1539.                                     n[k][0][0] = lastn[k] + lastslide;
  1540.                                     n[k][0][1] = vol[k];
  1541.                                 }
  1542.                             else n[k][0][0] += lastslide;
  1543.  
  1544.                             if ( n[k][0][0] > 856 ) n[k][0][0] = 856;
  1545.                             else
  1546.                             if ( n[k][0][0] < 113 ) n[k][0][0] = 113;
  1547.                         break;
  1548.  
  1549.                         /* Vibrato */
  1550.                         case 0x400:
  1551.                         /* Tremolo */
  1552.                         case 0x700:
  1553.                             // Ignore these effects.. not convertable
  1554.                         break;
  1555.  
  1556.                         /* Slide to & volume slide */
  1557.                         case 0x500:
  1558.                             if ( ( note || slideto ) && note != lastn[k] && sam->m < 128 )
  1559.                             {
  1560.                                 if ( note ) slideto = note;
  1561.  
  1562.                                 if ( slideto > lastn[k] )
  1563.                                 {
  1564.                                     n[k][0][0] = lastn[k] + lastslide * ( ticks - 1 );
  1565.                                     if ( n[k][0][0] > 856 ) n[k][0][0] = 856;
  1566.  
  1567.                                     if ( n[k][0][0] > slideto ) n[k][0][0] = slideto;
  1568.                                 }
  1569.                                 else
  1570.                                 {
  1571.                                     n[k][0][0] = lastn[k] - lastslide * ( ticks - 1 );
  1572.                                     if ( n[k][0][0] < 113 ) n[k][0][0] = 113;
  1573.  
  1574.                                     if ( n[k][0][0] < slideto ) n[k][0][0] = slideto;
  1575.                                 }
  1576.                             }
  1577.                             else n[k][0][0] = 0;
  1578.  
  1579.                             note = 0;
  1580.  
  1581.                         /* Vibrato & volume slide */
  1582.                         case 0x600:
  1583.                         /* Volume slide */
  1584.                         case 0xA00:
  1585.                             {
  1586.                                 int v;
  1587.  
  1588.                                 if ( !note ) v = vol[k];
  1589.                                 else v = sam->v;
  1590.  
  1591.                                 v += ( ticks - 1 ) * ( effect & 0x0F0 ); // Can't really slide
  1592.                                 v -= ( ticks - 1 ) * ( effect & 0x00F );
  1593.  
  1594.                                 if ( v > 127 ) v = 127;
  1595.                                 else if ( v < 0 ) v = 0;
  1596.  
  1597.                                 n[k][0][1] = v;
  1598.                                 break;
  1599.                             }
  1600.  
  1601.                         /* Set offset: pretend it's retrigger */
  1602.                         case 0x900:
  1603.                             if ( ( !n[k][0][0] || !sampnum ) && delay[k] )
  1604.                             {
  1605.                                 n[k][0][0] = lastn[k];
  1606.                                 n[k][0][1] = vol[k];
  1607.                             }
  1608.                         break;
  1609.  
  1610.                         /* Position jump: ignore, but break anyway */
  1611.                         case 0xB00:
  1612.                             patbreak = 1;
  1613.                         break;
  1614.  
  1615.                         /* Pattern break */
  1616.                         case 0xD00:
  1617.                             patbreak = 1 + 10 * ( effect & 0x0F0 ) + ( effect & 0x00F );
  1618.                         break;
  1619.  
  1620.                         /* Set volume */
  1621.                         case 0xC00:
  1622.                             n[k][0][1] = effect & 0x0FF;
  1623.                         break;
  1624.  
  1625.                         /* Set tempo */
  1626.                         case 0xF00:
  1627.                             {
  1628.                                 int temp;
  1629.  
  1630.                                 temp = effect & 0x0FF;
  1631.                                 if ( !temp ) temp = 1;
  1632.  
  1633.                                 if ( temp < 32 )
  1634.                                 {
  1635.                                     ticks = temp;
  1636.  
  1637.                                     /* Tempos act strangely */
  1638.                                     if ( TempoType )
  1639.                                     {
  1640.                                         bpm = 750 / temp;
  1641.                                         x = 80000 * temp;
  1642.                                     }
  1643.                                 }
  1644.                                 else
  1645.                                 {
  1646.                                     bpm = temp;
  1647.                                     x = 60000000 / temp;
  1648.                                 }
  1649.  
  1650.                                 if ( i ) break; // Only write tempo on track 0
  1651.  
  1652.                                 cnt += 6 + WriteVLQ( f2, timer );
  1653.                                 timer = 0;
  1654.  
  1655.                                 OutByte( f2, (unsigned char)255 ); // Meta-event
  1656.                                 OutByte( f2, 81 ); // Set tempo
  1657.                                 OutByte( f2, 3 );
  1658.                                 OutByte( f2, x >> 16 );
  1659.                                 OutByte( f2, ( x >> 8 ) & 0xFF );
  1660.                                 OutByte( f2, x & 0xFF );
  1661.                                 tempdone = 1;
  1662.  
  1663.                                 break;
  1664.                             }
  1665.  
  1666.                         /* Extended effects */
  1667.                         case 0xE00:
  1668.                             switch ( effect & 0x0F0 )
  1669.                             {
  1670.                                 /* Fine slide up */
  1671.                                 case 0x010:
  1672.                                     if ( !( effect & 0x00F ) || sam->m > 127 ) break;
  1673.  
  1674.                                     if ( !note )
  1675.                                         if ( !delay[k] ) break;
  1676.                                         else
  1677.                                         {
  1678.                                             n[k][h][0] = lastn[k] + ( effect & 0x00F );
  1679.                                             n[k][h][1] = vol[k];
  1680.                                         }
  1681.                                     else n[k][h][0] += effect & 0x00F;
  1682.                                 break;
  1683.  
  1684.                                 /* Fine slide down */
  1685.                                 case 0x020:
  1686.                                     if ( !( effect & 0x00F ) || sam->m > 127 ) break;
  1687.  
  1688.                                     if ( !note )
  1689.                                         if ( !delay[k] ) break;
  1690.                                         else
  1691.                                         {
  1692.                                             n[k][h][0] = lastn[k] - ( effect & 0x00F );
  1693.                                             n[k][h][1] = vol[k];
  1694.                                         }
  1695.                                     else n[k][h][0] -= effect & 0x00F;
  1696.                                 break;
  1697.  
  1698.                                 case 0x000: /* Set filter on/off */
  1699.                                 case 0x030: /* glissando on/off */
  1700.                                 case 0x040: /* set vibrato wave */
  1701.                                 case 0x050: /* set finetune */
  1702.                                 case 0x060: /* pattern loop */
  1703.                                 case 0x070: /* set tremolo wave */
  1704.                                 case 0x080: /* un-used */
  1705.                                 case 0x0F0: /* invert loop */
  1706.                                     // Can't do these in MIDI.. ignore
  1707.                                 break;
  1708.  
  1709.                                 /* Fine volume slide up */
  1710.                                 case 0x0A0:
  1711.                                 /* Fine volume slide down */
  1712.                                 case 0x0B0:
  1713.                                     {
  1714.                                         int v;
  1715.  
  1716.                                         v = sam->v;
  1717.                                         if ( effect & 0x0A0 ) v += effect & 0x00F;
  1718.                                         else v -= effect & 0x00F;
  1719.  
  1720.                                         if ( v < 0 ) v = 0;
  1721.                                         else
  1722.                                         if ( v > 127 ) v = 127;
  1723.  
  1724.                                         n[k][0][1] = v;
  1725.  
  1726.                                         break;
  1727.                                     }
  1728.  
  1729.                                 /* Retrigger sample */
  1730.                                 case 0x090:
  1731.                                     {
  1732.                                         int a, b, c;
  1733.  
  1734.                                         if ( !note && !delay[k] || !( effect & 0x00F ) ) break;
  1735.  
  1736.                                         a = effect & 0x00F;
  1737.                                         if ( !( ticks / a ) ) break;
  1738.  
  1739.                                         if ( !note )
  1740.                                         {
  1741.                                             n[k][0][0] = lastn[k];
  1742.                                             n[k][0][1] = vol[k];
  1743.                                         }
  1744.  
  1745.                                         c = 0;
  1746.                                         b = 1;
  1747.                                         a *= 48;
  1748.  
  1749.                                         while ( c < 48 )
  1750.                                         {
  1751.                                             n[k][c][0] = note;
  1752.                                             n[k][c][1] = n[k][0][1];
  1753.                                             c = b * a / ticks;
  1754.                                             b++;
  1755.                                         }
  1756.  
  1757.                                         break;
  1758.                                     }
  1759.  
  1760.                                 /* Cut sample */
  1761.                                 case 0x0C0:
  1762.                                     {
  1763.                                         int a;
  1764.  
  1765.                                         if ( !note && !delay[k] ) break;
  1766.  
  1767.                                         a = 48 * ( effect & 0x00F ) / ticks;
  1768.  
  1769.                                         if ( a > 47 ) break;
  1770.  
  1771.                                         if ( note ) n[k][a][0] = note;
  1772.                                         else n[k][a][0] = lastn[k];
  1773.  
  1774.                                         n[k][a][1] = 0;
  1775.  
  1776.                                         break;
  1777.                                     }
  1778.  
  1779.                                 /* Delay sample */
  1780.                                 case 0x0D0:
  1781.                                     {
  1782.                                         int a;
  1783.  
  1784.                                         if ( !note || !( effect & 0x00F ) ) break;
  1785.  
  1786.                                         a = 48 * ( effect & 0x00F ) / ticks;
  1787.                                         n[k][0][0] = 0;
  1788.  
  1789.                                         if ( a > 47 ) break;
  1790.  
  1791.                                         n[k][a][0] = note;
  1792.                                         n[k][a][1] = n[k][a][0];
  1793.  
  1794.                                         break;
  1795.                                     }
  1796.  
  1797.                                 /* Pattern pause */
  1798.                                 case 0x0E0:
  1799.                                     pause = 48 * ( effect & 0x00F );
  1800.                                 break;
  1801.                             }
  1802.                         break;
  1803.                         }
  1804.                     }
  1805.  
  1806.                     for ( h = 0; h < 48; h++ )
  1807.                     {
  1808.                         for ( k = 0; k < 4; k++ )
  1809.                         if ( n[k][h][0] )
  1810.                         {
  1811.                             /* Turn off old note on same channel */
  1812.                             if ( delay[k] )
  1813.                             {
  1814.                                 cnt += 3 + WriteVLQ( f2, timer );
  1815.                                 timer = 0;
  1816.  
  1817.                                 OutByte( f2, 0x80 + c ); // Note off
  1818.                                 OutByte( f2, ENOTE( lastn[k], 0 ) );
  1819.                                 OutByte( f2, RestrictVol( EVOL( vol[k] ) ) );
  1820.  
  1821.                                 if ( sam->t[1] )
  1822.                                 {
  1823.                                     cnt += 4;
  1824.                                     OutByte( f2, 0 );
  1825.                                     OutByte( f2, 0x80 + c );
  1826.                                     OutByte( f2, ENOTE( lastn[k], 1 ) );
  1827.                                     OutByte( f2, RestrictVol( EVOL( vol[k] ) ) );
  1828.  
  1829.                                     if ( sam->t[2] )
  1830.                                     {
  1831.                                         cnt += 4;
  1832.  
  1833.                                         OutByte( f2, 0 );
  1834.                                         OutByte( f2, 0x80 + c );
  1835.                                         OutByte( f2, ENOTE( lastn[k], 2 ) );
  1836.                                         OutByte( f2, RestrictVol( EVOL( vol[k] ) ) );
  1837.                                     }
  1838.                                 }
  1839.                                 delay[k] = 0;
  1840.                             }
  1841.  
  1842.                             lastn[k] = n[k][h][0];
  1843.                             n[k][h][0] = 0;
  1844.                             vol[k] = n[k][h][1];
  1845.                             cnt += 3 + WriteVLQ( f2, timer );
  1846.                             timer = 0;
  1847.  
  1848.                             OutByte( f2, 0x90 + c ); // Note on
  1849.                             OutByte( f2, ENOTE( lastn[k], 0 ) );
  1850.                             OutByte( f2, RestrictVol( EVOL( vol[k] ) ) );
  1851.  
  1852.                             if ( sam->t[1] )
  1853.                             {
  1854.                                 cnt += 4;
  1855.  
  1856.                                 OutByte( f2, 0 );
  1857.                                 OutByte( f2, 0x90 + c );
  1858.                                 OutByte( f2, ENOTE( lastn[k], 1 ) );
  1859.                                 OutByte( f2, RestrictVol( EVOL( vol[k] ) ) );
  1860.  
  1861.                                 if ( sam->t[2] )
  1862.                                 {
  1863.                                     cnt += 4;
  1864.  
  1865.                                     OutByte( f2, 0 );
  1866.                                     OutByte( f2, 0x90 + c );
  1867.                                     OutByte( f2, ENOTE( lastn[k], 2 ) );
  1868.                                     OutByte( f2, RestrictVol( EVOL( vol[k] ) ) );
  1869.                                 }
  1870.                             }
  1871.  
  1872.                             delay[k] = NoteLength( ANOTE( lastn[k] ), sam->l, bpm );
  1873.                         }
  1874.                         else
  1875.                         if ( delay[k] == 1 )
  1876.                         {
  1877.                             delay[k] = 0;
  1878.                             cnt += 3 + WriteVLQ( f2, timer );
  1879.  
  1880.                             timer = 0;
  1881.  
  1882.                             OutByte( f2, 0x80 + c ); // Note off
  1883.                             OutByte( f2, ENOTE( lastn[k], 0 ) );
  1884.                             OutByte( f2, RestrictVol( EVOL( vol[k] ) ) );
  1885.  
  1886.                             if ( sam->t[1] )
  1887.                             {
  1888.                                 cnt += 4;
  1889.  
  1890.                                 OutByte( f2, 0 );
  1891.                                 OutByte( f2, 0x80 + c );
  1892.                                 OutByte( f2, ENOTE( lastn[k], 1 ) );
  1893.                                 OutByte( f2, RestrictVol( EVOL( vol[k] ) ) );
  1894.  
  1895.                                 if ( sam->t[2] )
  1896.                                 {
  1897.                                     cnt += 4;
  1898.  
  1899.                                     OutByte( f2, 0 );
  1900.                                     OutByte( f2, 0x80 + c );
  1901.                                     OutByte( f2, ENOTE( lastn[k], 2 ) );
  1902.                                     OutByte( f2, RestrictVol( EVOL( vol[k] ) ) );
  1903.                                 }
  1904.                             }
  1905.                         }
  1906.                         else
  1907.                         if ( delay[k] > 0 ) delay[k]--;
  1908.  
  1909.                             timer++;
  1910.                     }
  1911.  
  1912.                     timer += pause;
  1913.  
  1914.                     if ( patbreak < 0 ) patbreak++;
  1915.                     else
  1916.                     if ( patbreak > 0 )
  1917.                     {
  1918.                         patbreak = 1 - patbreak;
  1919.  
  1920.                         while ( j )
  1921.                         {
  1922.                             j--;
  1923.                             Inskipp( f1, 16 ); // 16 bytes / song position
  1924.                         }
  1925.                     }
  1926.                 }
  1927.             }
  1928.  
  1929.             for ( k = 0; k < 4; k++ )
  1930.             if ( delay[k] )
  1931.             {
  1932.                 cnt += 3 + WriteVLQ( f2, timer );
  1933.                 timer = 0;
  1934.  
  1935.                 OutByte( f2, 0x80 + c ); // Note off
  1936.                 OutByte( f2, ENOTE( lastn[k], 0 ) );
  1937.                 OutByte( f2, RestrictVol( EVOL( vol[k] ) ) );
  1938.  
  1939.                 if ( sam->t[1] )
  1940.                 {
  1941.                     cnt += 4;
  1942.  
  1943.                     OutByte( f2, 0 );
  1944.                     OutByte( f2, 0x80 + c );
  1945.                     OutByte( f2, ENOTE( lastn[k], 1 ) );
  1946.                     OutByte( f2, RestrictVol( EVOL( vol[k] ) ) );
  1947.  
  1948.                     if ( sam->t[2] )
  1949.                     {
  1950.                         cnt += 4;
  1951.  
  1952.                         OutByte( f2, 0 );
  1953.                         OutByte( f2, 0x80 + c );
  1954.                         OutByte( f2, ENOTE( lastn[k], 2 ) );
  1955.                         OutByte( f2, RestrictVol( EVOL( vol[k] ) ) );
  1956.                     }
  1957.                 }
  1958.             }
  1959.         }
  1960.  
  1961.         if ( !i && !tempdone )
  1962.         {
  1963.             cnt += 7;
  1964.  
  1965.             OutByte( f2, 0 ); // Give the default 128 bpm if none done yet
  1966.             OutByte( f2, (unsigned char)255 );
  1967.             OutByte( f2, 81 );
  1968.             OutByte( f2, 3 );
  1969.             OutByte( f2, 7 );
  1970.             OutByte( f2, 39 );
  1971.             OutByte( f2, 14 );
  1972.         }
  1973.  
  1974.         cnt += 3 + WriteVLQ( f2, timer );
  1975.  
  1976.         OutByte( f2, (unsigned char)255 );
  1977.         OutByte( f2, 47 );
  1978.         OutByte( f2, 0 );
  1979.  
  1980.         AddToLog( inst, cnt ); // Process this later
  1981.  
  1982.         FGoto( f1, p2 );
  1983.     }
  1984.  
  1985.     FlushOut( f2 );
  1986.     WriteLog( f2->f );
  1987.     FGoto( f1, p1 );
  1988. }
  1989.